package com.thx.common.util;

import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;


/**
 * 文件工具.
 *
 * @author shiyan
 */
public class FileUtil {

  /**
   * 给文件重新命名 时间字符串 + 随机数.
   */
  public static String rename(String fileName) {

    Random random = new Random();
    int rannum = (int) (random.nextDouble() * (99999 - 10000 + 1)) + 10000;
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
    String nowTimeStr = dateFormat.format(new Date());
    String extName = getExtName(fileName);

    return nowTimeStr + rannum + "." + extName;
  }

  /**
   * 得到文件名的后缀(不包括.).
   */
  public static String getExtName(String fileName) {
    if (StringUtils.isNotBlank(fileName) && fileName.lastIndexOf(".") >= 0) {
      return fileName.substring(fileName.lastIndexOf(".") + 1);
    }
    return "";
  }

  /**
   * 复制单个文件.
   *
   * @param srcFileName 待复制的文件名
   * @param destFileName 目标文件名
   * @param overlay 如果目标文件存在，是否覆盖
   * @return 如果复制成功返回true，否则返回false
   */
  public static boolean copyFile(String srcFileName, String destFileName, boolean overlay) {
    File srcFile = new File(srcFileName);

    // 判断源文件是否存在
    if (!srcFile.exists()) {
      return false;
    } else if (!srcFile.isFile()) {
      return false;
    }

    // 判断目标文件是否存在
    File destFile = new File(destFileName);
    if (destFile.exists()) {
      // 如果目标文件存在并允许覆盖
      if (overlay) {
        // 删除已经存在的目标文件，无论目标文件是目录还是单个文件
        new File(destFileName).delete();
      }
    } else {
      // 如果目标文件所在目录不存在，则创建目录
      if (!destFile.getParentFile().exists()) {
        // 目标文件所在目录不存在
        if (!destFile.getParentFile().mkdirs()) {
          // 复制文件失败：创建目标文件所在目录失败
          return false;
        }
      }
    }

    // 复制文件
    int byteread = 0; // 读取的字节数
    InputStream in = null;
    OutputStream out = null;

    try {
      in = new FileInputStream(srcFile);
      out = new FileOutputStream(destFile);
      byte[] buffer = new byte[1024];

      while ((byteread = in.read(buffer)) != -1) {
        out.write(buffer, 0, byteread);
      }
      return true;
    } catch (FileNotFoundException ex) {
      return false;
    } catch (IOException ex) {
      return false;
    } finally {
      try {
        if (out != null) {
          out.close();
        }
        if (in != null) {
          in.close();
        }
      } catch (IOException ex) {
        ex.printStackTrace();
      }
    }
  }

  /**
   * 移动单个文件.
   *
   * @param srcFileName 待复制目录的文件名
   * @param destFileName 目标文件名
   * @param overlay 如果目标目录存在，是否覆盖
   * @return 如果移动成功返回true，否则返回false
   */
  public static boolean moveFile(String srcFileName, String destFileName, boolean overlay) {
    boolean copy = copyFile(srcFileName, destFileName, overlay);
    if (copy) {
      File srcFile = new File(srcFileName);
      srcFile.delete();
      return true;
    }
    return false;
  }

  /**
   * 复制整个目录的内容.
   *
   * @param srcDirName 待复制目录的目录名
   * @param destDirName 目标目录名
   * @param overlay 如果目标目录存在，是否覆盖
   * @return 如果复制成功返回true，否则返回false
   */
  public static boolean copyDirectory(String srcDirName, String destDirName, boolean overlay) {
    // 判断源目录是否存在
    File srcDir = new File(srcDirName);
    if (!srcDir.exists()) {
      return false;
    } else if (!srcDir.isDirectory()) {
      return false;
    }

    // 如果目标目录名不是以文件分隔符结尾，则加上文件分隔符
    if (!destDirName.endsWith(File.separator)) {
      destDirName = destDirName + File.separator;
    }
    File destDir = new File(destDirName);
    // 如果目标文件夹存在
    if (destDir.exists()) {
      // 如果允许覆盖则删除已存在的目标目录
      if (overlay) {
        new File(destDirName).delete();
      } else {
        return false;
      }
    } else {
      // 创建目的目录
      if (!destDir.mkdirs()) {
        return false;
      }
    }

    boolean flag = true;
    File[] files = srcDir.listFiles();
    if (files == null) {
      flag = false;
    } else {
      for (int i = 0; i < files.length; i++) {
        // 复制文件
        if (files[i].isFile()) {
          flag = copyFile(files[i].getAbsolutePath(), destDirName + files[i].getName(), overlay);
          if (!flag) {
            break;
          }
        } else if (files[i].isDirectory()) {
          flag =
              copyDirectory(files[i].getAbsolutePath(), destDirName + files[i].getName(), overlay);
          if (!flag) {
            break;
          }
        }
      }
    }

    return flag;
  }

  /**
   * 检查文件后缀名是否正确.
   */
  public static boolean checkFileType(String fileType, String extName) {
    boolean flag = false;
    if (extName != null && fileType != null) {
      String[] fileTypes = fileType.split(",");
      for (int i = 0; i < fileTypes.length; i++) {
        flag = flag || extName.equalsIgnoreCase(fileTypes[i].trim());
      }
    }
    return flag;
  }

  /**
   * 将字节写入文件.
   *
   * @param path 文件路径
   * @param stream 要写入的字节数组
   * @return 成功与否
   */
  public static boolean createFileByStream(String path, byte[] stream) {
    File file = new File(path);
    if (!file.exists()) {
      if (!file.getParentFile().exists()) {
        file.getParentFile().mkdirs();
      }
    }
    try {
      FileOutputStream os = new FileOutputStream(file);

      try {
        os.write(stream);
        os.flush();
        os.close();
        return true;
      } finally {
        os.close();
      }
    } catch (Exception ex) {
      ex.printStackTrace();
    }
    return false;
  }

  /**
   * 转换成人类友好的格式, 将字节转换成KB、MB、G.
   *
   * @param bytes 字节数
   * @return 人类友好容量格式
   */
  public static String formatSize(long bytes) {
    BigDecimal filesize = new BigDecimal(bytes);
    BigDecimal megabyte = new BigDecimal(1024 * 1024);
    BigDecimal gbyte = new BigDecimal(1024 * 1024 * 1024);
    BigDecimal kilobyte = new BigDecimal(1024);
    float returnValue = filesize.divide(megabyte, 2, BigDecimal.ROUND_UP).floatValue();
    if (returnValue < 1) {
      returnValue = filesize.divide(kilobyte, 2, BigDecimal.ROUND_UP).floatValue();
      return (returnValue + "KB");
    } else if (returnValue > 1 && returnValue < 1024) {
      return (returnValue + "MB");
    } else {
      returnValue = filesize.divide(gbyte, 2, BigDecimal.ROUND_UP).floatValue();
      return (returnValue + "G");
    }

  }

  /**
   * 获取文件的 MIME type.
   */
  public static String getMimeType(File file) {
    String mimetype = "";
    if (file.exists()) {
      String suffix = getExtName(file.getName());
      if (suffix.equalsIgnoreCase("png")) {
        mimetype = "image/png";
      } else if (suffix.equalsIgnoreCase("apk")) {
        mimetype = "application/vnd.android.package-archive";
      } else {
        javax.activation.MimetypesFileTypeMap mtMap = new javax.activation.MimetypesFileTypeMap();
        mimetype = mtMap.getContentType(file);
      }
    }
    return mimetype;
  }
}
